import os
from typing import AnyStr

if os.name != 'nt':
    raise Exception("Only NT OS mutex is supported")
else:
    from win32file import CloseHandle
    from win32event import (
        CreateMutex, ReleaseMutex, WaitForSingleObject,
        WAIT_OBJECT_0, WAIT_TIMEOUT, WAIT_ABANDONED, INFINITE
    )
    from os import PathLike, fspath


    class Mutex:
        # timeout in milliseconds
        def __init__(self, name: AnyStr | PathLike, initial_value: int = 1, timeout: int = INFINITE):
            self.name = fspath(name)
            self.name = self.name.replace('\\', '/')
            self.timeout = timeout
            self.initial_value = initial_value
            self._sem = CreateMutex(None, False, self.name)

        def __enter__(self):
            self.acquire()
            return self

        def __exit__(self, exc_type, exc_val, exc_tb):
            self.release()
            self.close()

        def acquire(self):
            result = WaitForSingleObject(self._sem, self.timeout)
            if result == WAIT_OBJECT_0:
                return self
            elif result == WAIT_TIMEOUT:
                raise Exception('mutex not acquired')
            elif result == WAIT_ABANDONED:
                raise Exception('mutex abandoned')

        def release(self):
            ReleaseMutex(self._sem)

        def close(self):
            CloseHandle(self._sem)
            self._sem = None
